package com.higgins.eventtracking.client.health;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.higgins.eventtracking.client.EventTrackingService;
import com.higgins.eventtracking.client.EventTrackingServiceAsync;
import com.higgins.eventtracking.client.FinanceTrackingService;
import com.higgins.eventtracking.client.FinanceTrackingServiceAsync;
import com.higgins.eventtracking.client.SecurityAccessDeniedException;
import com.higgins.eventtracking.client.dto.DynamicTypeDTO;
import com.higgins.eventtracking.client.dto.HealthEventDTO;
import com.higgins.eventtracking.client.dto.WeightEventDTO;

public class PopupQuestionBox {
	private final FinanceTrackingServiceAsync financeTrackingService = GWT
				.create(FinanceTrackingService.class);
	final DialogBox dialogBox = new DialogBox();
	final Button closeButton = new Button("Close");
	final Button skipButton = new Button("Skip");
	private final EventTrackingServiceAsync greetingService = GWT
		.create(EventTrackingService.class);
	int questionIndex = 0;
	
	public void checkForQuestions()	{
		if (hasNextQuestion())	{
			askNextQuestion();
		}
	}
	private void askNextQuestion()	{
		switch(questionIndex)	{
		case 0:
			frameOfMind();
			break;
		case 1:
			wellBeing();
			break;
		case 2:
			energy();
			break;
		case 3:
			bloated();
			break;
		case 4:
			weight();
			break;
		case 5:
			bodyFat();
			break;
		case 6:
			water();
			break;
		case 7:
			muscle();
			break;
		case 8:
			fatCalipers();
			break;
		case 9:
			calfs();
			break;
		case 10:
			hamstrings();
			break;	
		case 11:
			waist();
			break;
		case 12:
			chest();
			break;
		case 13:
			shoulders();
			break;
		case 14:
			neck();
			break;
		case 15:
			leftArm();
			break;
		case 16:
			leftForearm();
			break;
		case 17:
			rightArm();
			break;
		case 18:
			rightForeArm();
			break;			
		}
		questionIndex++;
	}
	private boolean hasNextQuestion()	{
		return questionIndex < 19;
	}
	
	private void frameOfMind()	{
		greetingService.frameOfMindSetToday(new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					try	{
						retrieveFrameOfMinds();
					} catch (Exception e)	{
						if (hasNextQuestion())	{
								askNextQuestion();
						} else {
							dialogBox.hide();
						}
					}
				} else if (hasNextQuestion())	{
						askNextQuestion();
				} else {
					dialogBox.hide();
				}
			}  });
	}
	private void retrieveFrameOfMinds() throws IllegalArgumentException, SecurityAccessDeniedException	{
		financeTrackingService.retrieveDynamicTypes("FrameOfMindType", new AsyncCallback<List<DynamicTypeDTO>>()  {

			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(List<DynamicTypeDTO> results) {
				List<String> answers = new ArrayList<String>();
				for (DynamicTypeDTO dto:results)	{
					if (dto.getSubType()==null || !dto.getSubType())	{
						answers.add(dto.getDynamicType());
					}
				}
//				answers.add("Bored");
//				answers.add("Depressed");
//				answers.add("Anxious");
				setFrameOfMindDialogBox("What frame of mind are you in today?", answers);
			}
		});
	}
	private void wellBeing()	{
		greetingService.healthEventToday("Well Being", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					answers.add("0");
					answers.add("1");
					answers.add("2");
					answers.add("3");
					answers.add("4");
					answers.add("5");
					answers.add("6");
					answers.add("7");
					answers.add("8");
					answers.add("9");
					answers.add("10");
					setHealthEventDialogBox("Well Being", "How much Well Being do you have today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });
	}
	private void energy()	{
		greetingService.healthEventToday("Energy", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					answers.add("0");
					answers.add("1");
					answers.add("2");
					answers.add("3");
					answers.add("4");
					answers.add("5");
					answers.add("6");
					answers.add("7");
					answers.add("8");
					answers.add("9");
					answers.add("10");
					setHealthEventDialogBox("Energy", "How much Energy do you have today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });
	}
	private void bloated()	{
		greetingService.healthEventToday("Bloated", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					answers.add("0");
					answers.add("1");
					answers.add("2");
					answers.add("3");
					answers.add("4");
					answers.add("5");
					answers.add("6");
					answers.add("7");
					answers.add("8");
					answers.add("9");
					answers.add("10");
					setHealthEventDialogBox("Bloated", "How much Bloating do you have today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });
	}
	private void weight()	{
		greetingService.weightEventToday("WeightKG", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					Double count = 66.5; 
					while (count < 75.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.1;
					}
					setWeightEventDialogBox("WeightKG", "How Heavy are you today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });
	}
	private void bodyFat()	{
		greetingService.weightEventToday("BodyFatPerc", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 12.0; 
					while (count < 25.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.1;
					}
					setWeightEventDialogBox("BodyFatPerc", "What Percentage Body Fat are you today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });
	}
	private void water()	{
		greetingService.weightEventToday("WaterPerc", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 50.0; 
					while (count < 70.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.1;
					}
					setWeightEventDialogBox("WaterPerc", "What Percentage Water are you today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });		
	}
	private void muscle()	{
		greetingService.weightEventToday("MusclePerc", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 46.0; 
					while (count < 70.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.1;
					}
					setWeightEventDialogBox("MusclePerc", "What Percentage Muscle are you today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });		
	}
	private void fatCalipers()	{
		greetingService.weightEventToday("FatCalipers", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 16.0; 
					while (count < 24.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 1.0;
					}
					setWeightEventDialogBox("FatCalipers", "What do the Fat Calipers say today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });	
	}

	private void calfs()	{
		greetingService.weightEventToday("Calfs", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 33.0; 
					while (count < 42.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.5;
					}
					setWeightEventDialogBox("Calfs", "How big are your Calfs today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });			
	}
	private void hamstrings() 	{
		greetingService.weightEventToday("Hamstrings", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 45.0; 
					while (count < 60.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.5;
					}
					setWeightEventDialogBox("Hamstrings", "How big are your Hamstrings today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });			
	}
	private void waist()	{
		greetingService.weightEventToday("Waist", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 85.0; 
					while (count < 105.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.5;
					}
					setWeightEventDialogBox("Waist", "How big are is your Waist today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });			
	}
	private void chest()	{
		greetingService.weightEventToday("Chest", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 90.0; 
					while (count < 110.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.5;
					}
					setWeightEventDialogBox("Chest", "How big is your Chest today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });	
	}
	private void shoulders()	{
		greetingService.weightEventToday("Shoulders", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 110.0; 
					while (count < 130.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.5;
					}
					setWeightEventDialogBox("Shoulders", "How big are your Shoulders today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });	
	}
	private void neck()	{
		greetingService.weightEventToday("Neck", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 33.0; 
					while (count < 40.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.5;
					}
					setWeightEventDialogBox("Neck", "How big is your Neck today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });	
	}
	private void leftArm()	{
		greetingService.weightEventToday("LeftArm", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 33.0; 
					while (count < 42.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.5;
					}
					setWeightEventDialogBox("LeftArm", "How big is your Left Arm today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });	
	}
	private void leftForearm()	{
		greetingService.weightEventToday("LeftForeArm", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 25.0; 
					while (count < 35.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.5;
					}
					setWeightEventDialogBox("LeftForeArm", "How big is your Left Fore Arm today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });	
	}
	private void rightArm()	{
		greetingService.weightEventToday("RightArm", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 33.0; 
					while (count < 42.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.5;
					}
					setWeightEventDialogBox("RightArm", "How big is your Right Arm today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });	
	}
	private void rightForeArm()	{
		greetingService.weightEventToday("RightForeArm", new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				if (!result)	{
					List<String> answers = new ArrayList<String>();
					double count = 25.0; 
					while (count < 35.0)	{
						String formatted = NumberFormat.getFormat("0.0").format(count);
						answers.add("" + formatted);
						count = count + 0.5;
					}
					setWeightEventDialogBox("RightForeArm", "How big is your Right Fore Arm today?", answers);
				} else if (hasNextQuestion())	{
					askNextQuestion();
			} else {
				dialogBox.hide();
			}
		}  });	
	}

	private void storeFrameOfMindResponse(String response)	{
		greetingService.insertFrameOfMind(response, new AsyncCallback<Boolean>()  {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
			}  });
	}
	private void storeHealthEventResponse(String healthEventType, String response)	{
		HealthEventDTO healthEvent = new HealthEventDTO();
		healthEvent.setHealthEventType(healthEventType);
		healthEvent.setHealthEventIntensityScale(Integer.parseInt(response));
		healthEvent.setTimestamp(new Date());
		greetingService.insertHealthEvent(healthEvent, new AsyncCallback<String>()  {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(String result) {
			}  });
	}
	private void storeWeightEventResponse(String weightEventType, String response)	{
		String formatted = NumberFormat.getFormat("0.0").format(Double.parseDouble(response));

		WeightEventDTO weightEvent = new WeightEventDTO();
		weightEvent.setWeightEventType(weightEventType);
		weightEvent.setWeightEventScale(Double.parseDouble(formatted));
		weightEvent.setTimestamp(new Date());
		greetingService.insertWeightEvent(weightEvent, new AsyncCallback<String>()  {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(String result) {
			}  });
	}
	
	private void setFrameOfMindDialogBox(String question, List<String> possibleAnswers)	{
		dialogBox.clear();
		dialogBox.setText("Question:");
		dialogBox.setAnimationEnabled(true);
		closeButton.getElement().setId("closeButton");
		VerticalPanel dialogVPanel = new VerticalPanel();
		dialogVPanel.addStyleName("dialogVPanel");
		dialogVPanel.add(new HTML("<br><b>" + question + ":</b>"));
		dialogVPanel.add(newFrameOfMindListBox(possibleAnswers));
		dialogVPanel.add(skipButton);
		dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
		dialogVPanel.add(closeButton);
		dialogBox.setWidget(dialogVPanel);

		closeButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				dialogBox.hide();
			}
		});
		dialogBox.setText("Question:");
		dialogBox.center();
		dialogBox.setPopupPosition(25, 0);
		closeButton.setFocus(true);		
	}
	private void setHealthEventDialogBox(String healthEventType, String question, List<String> possibleAnswers)	{
		dialogBox.clear();
		dialogBox.setText("Question:");
		dialogBox.setAnimationEnabled(true);
		closeButton.getElement().setId("closeButton");
		VerticalPanel dialogVPanel = new VerticalPanel();
		dialogVPanel.addStyleName("dialogVPanel");
		dialogVPanel.add(new HTML("<br><b>" + question + ":</b>"));
		dialogVPanel.add(newHealthEventListBox(healthEventType, possibleAnswers));
		dialogVPanel.add(new Button("Skip"));
		dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
		dialogVPanel.add(closeButton);
		dialogBox.setWidget(dialogVPanel);

		closeButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				dialogBox.hide();
			}
		});
		dialogBox.setText("Question:");
		dialogBox.center();
		dialogBox.setPopupPosition(25, 0);
		closeButton.setFocus(true);		
	}	
	private void setWeightEventDialogBox(String weightEventType, String question, List<String> possibleAnswers)	{
		dialogBox.clear();
		dialogBox.setText("Question:");
		dialogBox.setAnimationEnabled(true);
		closeButton.getElement().setId("closeButton");
		VerticalPanel dialogVPanel = new VerticalPanel();
		dialogVPanel.addStyleName("dialogVPanel");
		dialogVPanel.add(new HTML("<br><b>" + question + ":</b>"));
		dialogVPanel.add(newWeightEventListBox(weightEventType, possibleAnswers));
		dialogVPanel.add(new Button("Skip"));
		dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
		dialogVPanel.add(closeButton);
		dialogBox.setWidget(dialogVPanel);

		closeButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				dialogBox.hide();
			}
		});
		dialogBox.setText("Question:");
		dialogBox.center();
		dialogBox.setPopupPosition(25, 0);
		closeButton.setFocus(true);		
	}	
	private ListBox newFrameOfMindListBox(List<String> possibleAnswer)	{
		final ListBox listBox = new ListBox();
		listBox.addItem("");
		for (String answer:possibleAnswer)	{
			listBox.addItem(answer);
		}
		listBox.addChangeHandler(new ChangeHandler()  {
			@Override
			public void onChange(ChangeEvent event) {
				storeFrameOfMindResponse(listBoxSelectedItem(listBox));
				if (hasNextQuestion())	{
					askNextQuestion();
				} else {
					dialogBox.hide();
				}
			}  });
		listBox.setSelectedIndex(0);
		return listBox;
	}
	private ListBox newHealthEventListBox(final String healthEvent, List<String> possibleAnswer)	{
		final ListBox listBox = new ListBox();
		listBox.addItem("");
		for (String answer:possibleAnswer)	{
			listBox.addItem(answer);
		}
		listBox.addChangeHandler(new ChangeHandler()  {
			@Override
			public void onChange(ChangeEvent event) {
				storeHealthEventResponse(healthEvent, listBoxSelectedItem(listBox));
				if (hasNextQuestion())	{
					askNextQuestion();
				} else {
					dialogBox.hide();
				}
			}  });
		listBox.setSelectedIndex(0);
		return listBox;
	}
	
	private ListBox newWeightEventListBox(final String weightEvent, List<String> possibleAnswer)	{
		final ListBox listBox = new ListBox();
		listBox.addItem("");
		for (String answer:possibleAnswer)	{
			listBox.addItem(answer);
		}
		listBox.addChangeHandler(new ChangeHandler()  {
			@Override
			public void onChange(ChangeEvent event) {
				storeWeightEventResponse(weightEvent, listBoxSelectedItem(listBox));
				if (hasNextQuestion())	{
					askNextQuestion();
				} else {
					dialogBox.hide();
				}
			}  });
		listBox.setSelectedIndex(0);
		return listBox;
	}
	
	private String listBoxSelectedItem(ListBox listBox)	{
		int index = listBox.getSelectedIndex();
		return listBox.getItemText(index);
	}
}
